<script setup>
import { ref, onMounted } from 'vue'
import { Map, View } from 'ol'
import TileLayer from 'ol/layer/Tile'
import XYZ from 'ol/source/XYZ'
import VectorLayer from 'ol/layer/Vector'
import VectorSource from 'ol/source/Vector'
import Draw from 'ol/interaction/Draw'
import Style from 'ol/style/Style'
import Stroke from 'ol/style/Stroke'
import Fill from 'ol/style/Fill'
import Circle from 'ol/style/Circle'
import WKT from 'ol/format/WKT'
import GeoJSON from 'ol/format/GeoJSON'
import { transform } from 'ol/proj'
import 'ol/ol.css'
import * as turf from '@turf/turf'

const mapRef = ref(null)
const map = ref(null)
const drawSource = ref(null)
const drawLayer = ref(null)
const resultSource = ref(null)
const resultLayer = ref(null)
const drawInteraction = ref(null)
const drawType = ref('Point')
const bufferDistance = ref(1000)
const bufferUnit = ref('米') // 距离单位：米或度
const errorMessage = ref('')

onMounted(() => {
  // 初始化地图
  map.value = new Map({
    target: mapRef.value,
    layers: [
      new TileLayer({
        source: new XYZ({
          url: 'http://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}',
          crossOrigin: 'anonymous'
        })
      })
    ],
    view: new View({
      center: [104, 35], // 地图中心坐标（经度，纬度）- 设置为中国中心
      zoom: 5,         // 初始缩放级别
      projection: 'EPSG:4326' // 使用WGS84坐标系
    })
  })
  
  // 创建绘制数据源和图层
  drawSource.value = new VectorSource()
  drawLayer.value = new VectorLayer({
    source: drawSource.value,
    style: new Style({
      image: new Circle({
        radius: 5,
        fill: new Fill({ color: 'blue' })
      }),
      stroke: new Stroke({
        color: 'blue',
        width: 2
      }),
      fill: new Fill({
        color: 'rgba(0, 0, 255, 0.1)'
      })
    })
  })
  map.value.addLayer(drawLayer.value)
  
  // 创建结果数据源和图层
  resultSource.value = new VectorSource()
  resultLayer.value = new VectorLayer({
    source: resultSource.value,
    style: new Style({
      stroke: new Stroke({
        color: 'red',
        width: 3
      }),
      fill: new Fill({
        color: 'rgba(255, 0, 0, 0.3)'
      })
    })
  })
  map.value.addLayer(resultLayer.value)
  
  // 添加绘制交互
  addDrawInteraction()
})

// 添加绘制交互
function addDrawInteraction() {
  if (drawInteraction.value) {
    map.value.removeInteraction(drawInteraction.value)
  }
  drawInteraction.value = new Draw({
    source: drawSource.value,
    type: drawType.value
  })
  map.value.addInteraction(drawInteraction.value)

  // 监听绘制完成事件
  drawInteraction.value.on('drawend', function(event) {
    const feature = event.feature
    processBuffer(feature)
  })
}

// 执行缓冲区分析
function processBuffer(feature) {
  errorMessage.value = ''
  try {
    // 1. 获取几何对象
    const geometry = feature.getGeometry()
    const wktFormat = new WKT()
    
    // 2. 处理距离单位
    let distance = parseFloat(bufferDistance.value) || 1000
    let geometryForBuffer = geometry.clone()
    let targetProjection = 'EPSG:4326' // 默认投影
    
    // 如果单位是米，将几何图形转换到EPSG:3857投影（Web墨卡托），该投影下距离单位是米
    if (bufferUnit.value === '米') {
      geometryForBuffer.transform('EPSG:4326', 'EPSG:3857')
      targetProjection = 'EPSG:3857'
    }
    
    // 3. 构建WPS请求
    const wktString = wktFormat.writeGeometry(geometryForBuffer)

    // 构建正确的WPS请求XML，确保命名空间和参数正确
    const wpsRequest = `<?xml version="1.0" encoding="UTF-8"?>
<wps:Execute service="WPS" version="1.0.0"
    xmlns:wps="http://www.opengis.net/wps/1.0.0"
    xmlns:ows="http://www.opengis.net/ows/1.1"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd">
  <ows:Identifier>JTS:buffer</ows:Identifier>
  <wps:DataInputs>
    <wps:Input>
      <ows:Identifier>geom</ows:Identifier>
      <wps:Data>
        <wps:ComplexData mimeType="application/wkt"><![CDATA[${wktString}]]></wps:ComplexData>
      </wps:Data>
    </wps:Input>
    <wps:Input>
      <ows:Identifier>distance</ows:Identifier>
      <wps:Data>
        <wps:LiteralData>${distance}</wps:LiteralData>
      </wps:Data>
    </wps:Input>
    <wps:Input>
      <ows:Identifier>quadrantSegments</ows:Identifier>
      <wps:Data>
        <wps:LiteralData>8</wps:LiteralData>
      </wps:Data>
    </wps:Input>
    <wps:Input>
      <ows:Identifier>capStyle</ows:Identifier>
      <wps:Data>
        <wps:LiteralData>round</wps:LiteralData>
      </wps:Data>
    </wps:Input>
  </wps:DataInputs>
  <wps:ResponseForm>
    <wps:RawDataOutput mimeType="application/json">
      <ows:Identifier>result</ows:Identifier>
    </wps:RawDataOutput>
  </wps:ResponseForm>
</wps:Execute>`

    // 3. 发送WPS请求
    const xhr = new XMLHttpRequest()
    // 使用相对路径，通过Vite代理解决CORS问题
    // 在URL中添加request参数，确保GeoServer能识别请求类型
    xhr.open('POST', '/geoserver/wps?request=Execute', true)
    xhr.setRequestHeader('Content-Type', 'text/xml;charset=UTF-8')
    xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest')
    
    // 如果GeoServer需要登录，添加认证头
    const credentials = btoa('admin:geoserver')
    xhr.setRequestHeader('Authorization', 'Basic ' + credentials)
    
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          try {
            // 4. 解析WPS响应
            const response = JSON.parse(xhr.responseText)
            // 5. 显示分析结果
            displayBufferResult(response)
          } catch (e) {
            errorMessage.value = '解析WPS响应失败: ' + e.message
          }
        } else {
          errorMessage.value = 'WPS服务请求失败: ' + xhr.status + ' ' + xhr.statusText
        }
      }
    }
    
    xhr.onerror = function () {
      errorMessage.value = '网络错误，请检查GeoServer服务是否正常运行'
    }
    
    xhr.send(wpsRequest)
  } catch (e) {
    errorMessage.value = '处理缓冲区分析时出错: ' + e.message
  }
}

// 显示缓冲区分析结果
function displayBufferResult(response) {
  try {
    // 清空之前的结果
    resultSource.value.clear()
    
    // 解析GeoJSON响应
    const geoJsonFormat = new GeoJSON()
    let features = geoJsonFormat.readFeatures(response)
    
    // 如果单位是米，缓冲区结果是EPSG:3857投影，需要转换回EPSG:4326
    if (bufferUnit.value === '米') {
      features.forEach(feature => {
        const geometry = feature.getGeometry()
        geometry.transform('EPSG:3857', 'EPSG:4326')
      })
    }
    
    resultSource.value.addFeatures(features)
  } catch (e) {
    errorMessage.value = '显示分析结果失败: ' + e.message
  }
}

// 清除结果
function clearResults() {
  drawSource.value.clear()
  resultSource.value.clear()
  errorMessage.value = ''
}

// 绘制类型变化处理
function handleDrawTypeChange() {
  addDrawInteraction()
}
</script>

<template>
  <div class="map-container">
    <h1>WPS空间分析</h1>
    <div class="controls">
      <label>绘制类型:
        <select v-model="drawType" @change="handleDrawTypeChange">
          <option value="Point">点</option>
          <option value="LineString">线</option>
          <option value="Polygon">多边形</option>
        </select>
      </label>
      <label>缓冲区距离:
        <input type="number" v-model="bufferDistance" min="0">
        <select v-model="bufferUnit">
          <option value="米">米</option>
          <option value="度">度</option>
        </select>
      </label>
      <button @click="clearResults">清除结果</button>
    </div>
    <div v-if="errorMessage" class="error-message">{{ errorMessage }}</div>
    <div ref="mapRef" class="map"></div>
  </div>
</template>

<style scoped>
.map-container {
  width: 100%;
  height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  font-family: Arial, sans-serif;
}

h1 {
  margin: 20px 0;
  color: #333;
  font-size: 24px;
}

.controls {
  padding: 10px;
  background: #f0f0f0;
  border-radius: 8px;
  margin-bottom: 10px;
  display: flex;
  gap: 15px;
  align-items: center;
}

.controls label {
  display: flex;
  align-items: center;
  gap: 5px;
  font-weight: bold;
  color: #555;
}

.controls select,
.controls input {
  padding: 5px;
  border: 1px solid #ccc;
  border-radius: 4px;
  font-size: 14px;
}

.controls button {
  padding: 5px 15px;
  background: #4CAF50;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  transition: background 0.3s;
}

.controls button:hover {
  background: #45a049;
}

.error-message {
  color: red;
  margin-bottom: 10px;
  padding: 8px;
  background: #ffebee;
  border-radius: 4px;
  width: 90%;
  text-align: center;
}

.map {
  width: 90%;
  height: 80vh;
  border: 1px solid #ccc;
  border-radius: 8px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
</style>